home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1993 July / InfoMagic USENET CD-ROM July 1993.ISO / sources / unix / volume14 / nntp1.5 / part05 < prev    next >
Encoding:
Internet Message Format  |  1988-04-18  |  50.6 KB

  1. Subject:  v14i051:  Network News Transfer Protocol, version 1.5, Part05/09
  2. Newsgroups: comp.sources.unix
  3. Sender: sources
  4. Approved: rsalz@uunet.UU.NET
  5.  
  6. Submitted-by: Phil Lapsley <phil@ucbvax.berkeley.edu>
  7. Posting-number: Volume 14, Issue 51
  8. Archive-name: nntp1.5/part05
  9.  
  10. #! /bin/sh
  11. # This is a shell archive.  Remove anything before this line, then unpack
  12. # it by saving it into a file and typing "sh file".  To overwrite existing
  13. # files, type "sh file -c".  You can also feed this as standard input via
  14. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  15. # will see the following message at the end:
  16. #        "End of archive 5 (of 9)."
  17. # Wrapped by rsalz@fig.bbn.com on Tue Apr 19 18:16:43 1988
  18. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  19. if test -f './README' -a "${1}" != "-c" ; then 
  20.   echo shar: Will not clobber existing file \"'./README'\"
  21. else
  22. echo shar: Extracting \"'./README'\" \(6865 characters\)
  23. sed "s/^X//" >'./README' <<'END_OF_FILE'
  24. NNTP README        January 23, 1988    For version 1.5 NNTP package
  25. X
  26. X[See the file CHANGES to see differences between this version and
  27. older versions.]
  28. X
  29. INTRODUCTION
  30. X
  31. X     This package contains everything (well, most of it, I hope) that
  32. you'll need to implement a remote news server running the NNTP protocol.
  33. X
  34. X     A brief tour of the directories and their programs:
  35. X
  36. X    server        Source for the NNTP news server daemon.
  37. X
  38. X    rrnpatches    Patches to rn #39 to allow remote news reading.
  39. X
  40. X    inews        A "mini-inews" written by Steven Grady
  41. X            <grady@postgres.berkeley.edu> which allows
  42. X             remote posting without changing much else.
  43. X
  44. X    xmit        An active transmission client for transferring
  45. X            news, written by Erik Fair; see note below.
  46. X
  47. X    common        Common stuff (response codes, configuration info,
  48. X            and some client library routines) for the
  49. X            the news server and the clients.  The "conf.h"
  50. X            file here needs to be edited to reflect
  51. X            the peculiarities of your system.
  52. X
  53. X    support        Some support files and scripts.
  54. X
  55. X    doc        Documentation on the server, including manual
  56. X            pages.  Manual pages for rrn are in rrn/.
  57. X
  58. X    xfer        A passive reception client which uses the
  59. X            NEWNEWS command to retrieve news from a remote
  60. X            server.  Written by Brian Kantor, this software
  61. X            is UNSUPPORTED.
  62. X
  63. X     Each directory has associated with it a README file.
  64. This file will try to give enough information for you to get things
  65. running and installed, but the README in each directory has more
  66. details for each subset of the NNTP package.  You may also want to print
  67. a copy of doc/rfc977, which describes the NNTP protocol.
  68. X
  69. INTRODUCTION TO NNTP INSTALLATION
  70. X
  71. X     First, figure out what you are trying to do (this is good
  72. advice under most circumstances, and it is especially apropos here).
  73. NNTP can be used for two things:  (1) Remote news reading, where news
  74. is stored on one machine and read from remote machines across a
  75. high-speed local area network such as Ethernet, and (2) News transfer,
  76. where news is transmitted to NNTP servers on remote machines over
  77. either local or long-haul networks.
  78. X
  79. X     NNTP "server" machines are machines that have a full installation
  80. of USENET news on them.  An NNTP process, the "server", allows remote
  81. sites to connect to the server machine and read or transfer news.
  82. The server machine DOES NOT NEED "reader client" software such as
  83. X"rrn".  It MAY NEED "transmission client" software such as "nntpxmit"
  84. if you want to use NNTP to transfer news.
  85. X
  86. X     NNTP "client" machines do not have a full installation of USENET
  87. news on them.  They get their news from an NNTP server machine across
  88. the network.  They DO have NNTP "reader clients" such as "rrn" installed
  89. on them.
  90. X
  91. X     In summary,
  92. X
  93. X    >>> A full client installation of NNTP requires the following
  94. X        files (suitable for rdist, assuming standard directories):
  95. X
  96. NEWS = ( /usr/local/{Pnews,Rnmail,inews,rn,rrn,newsetup,newsgroups,lib/rn}
  97. X    /usr/man/catl/{Pnews,Rnmail,rn,newsetup,newsgroups}.1 )
  98. X
  99. X        You DO NOT need any of the normal news junk (e.g.,
  100. X        /usr/lib/news, postnews, checknews, readnews) on CLIENT
  101. X        systems.
  102. X
  103. X        You DO need these on SERVER systems.
  104. X
  105. X     An important note:
  106. X
  107. X    The NNTP server assumes that the history file format
  108. X    is 2.11 or 2.10.3; therefore you need 2.11 news on your
  109. X    server machine.
  110. X
  111. X    >>>>> Get 2.11 news if you don't have it.
  112. X
  113. GENERAL INSTALLATION
  114. X
  115. X     Time for a general and cohesive Plan:
  116. X
  117. X     Regardless of whether you are making a server or a client NNTP
  118. setup, you will have to edit common/conf.h to reflect your system's
  119. setup.  So,
  120. X
  121. X     1. Look at common/README.  This will explain the stuff
  122. X    needs to be tailored for your system in common/conf.h.
  123. X    Make the necessary changes to reflect your system.
  124. X
  125. X    If you are running with System V or Excelan TCP/IP,
  126. X    please read Stan Barber's instructions in common/README.SYSV
  127. X
  128. X    If you have an HPUX machine, please read common/README.HPUX
  129. X
  130. X     Now, at this point, what you do depends on whether you are
  131. installing a server system or a client system.
  132. X
  133. SERVER INSTALLATION
  134. X
  135. X     2. Type "make server" in this directory.
  136. X
  137. X     3. Type "make install_server" in this directory.
  138. X
  139. CLIENT INSTALLATION
  140. X
  141. X     2. You must configure "rrn", the remote newsreading client.
  142. X        cd into "rrnpatches", and read README_RRN.  This will explain
  143. X        how to apply the patches supplied to turn rn #39 into rrn #39.
  144. X
  145. X     3. Type "make client" in this directory.
  146. X
  147. X     4. Type "make install_client" in this directory.
  148. X
  149. IF YOU HAVE PROBLEMS
  150. X
  151. X     You can get to me via electronic mail at the following addresses:
  152. X
  153. X    Internet:        phil@ucbvax.berkeley.edu
  154. X    UUCP:            ...!ucbvax!phil
  155. X    Telephone (home):    (415) 848-8409
  156. X    Telephone (work):    (415) 642-7447
  157. X
  158. X     I'm very interested in learning what hacks need to be made to
  159. nntpd to get it to work on various systems, and certainly, if there are
  160. outright bugs, please let me know.  Bug reports and fixes for nntp are
  161. posted to the newsgroup "news.software.nntp".  Announcements of new
  162. versions of nntp software are posted there too.
  163. X
  164. X     I'll support bugs caused by my additions/hacks to turn "rn" into
  165. X"rrn" (hopefully Larry Wall will be supporting this soon...) but please
  166. don't send me reports about things that were already in rn itself.
  167. Also, if you add features to rrn, I probably am not interested in
  168. supporting them unless they are really necessary; every change I make
  169. to rrn is something that I have to hack into future releases of rn, so
  170. the fewer changes, the better.
  171. X
  172. ACKNOWLEDGEMENTS
  173. X
  174. X     I'd like to thank the various people who both inspired and helped
  175. to make NNTP a reality:  Erik Fair, whose criticism and suggestions
  176. helped mold NNTP (and who wrote the active transmission client); Brian
  177. Kantor, who really got me motivated enough to finish the thing, and
  178. whose work on the RFC was *tremendous*; Steven Grady, who wrote the
  179. inews interface (and wasted countless hours only to have his work
  180. dashed periodically...); Mike Meyer, who beta tested the software and
  181. pointed out numerous problems; Bob Henry, who let me have the resources
  182. so that it got done; Peter Yee, who repeated enough good ideas to get
  183. me to include them; all the folks who had patience with me and didn't
  184. go off and write this themselves (jsq, you listening?  My thanks.);
  185. Chuq von Rospach and the members of lan-news; Gene Spafford for
  186. eliminating having to include 1 MB of source to rn by a set of patches;
  187. Matt Thomas for adding support for DECNET; Stan Barber for adding
  188. System V/Excelan support and putting up with my sloth; the kind folks
  189. who beta tested version 1.4 and put up with stupid bugs and provided
  190. helpful feedback, notably Craig Leres, Matt Thomas, Wengyik Yeong, and
  191. Stan Barber; all the individuals who have reported bugs or suggested
  192. improvements (see CHANGES for a list); and probably many other people
  193. I've neglected to mention.  My thanks to all.
  194. X
  195. X                        Phil Lapsley
  196. X                        26 February 1988
  197. END_OF_FILE
  198. if test 6865 -ne `wc -c <'./README'`; then
  199.     echo shar: \"'./README'\" unpacked with wrong size!
  200. fi
  201. # end of './README'
  202. fi
  203. if test -f './rrnpatches/Configure.pat' -a "${1}" != "-c" ; then 
  204.   echo shar: Will not clobber existing file \"'./rrnpatches/Configure.pat'\"
  205. else
  206. echo shar: Extracting \"'./rrnpatches/Configure.pat'\" \(6499 characters\)
  207. sed "s/^X//" >'./rrnpatches/Configure.pat' <<'END_OF_FILE'
  208. X*** rn/Configure    Sun Mar 15 19:54:19 1987
  209. X--- rrn/Configure    Thu Feb 25 20:56:09 1988
  210. X***************
  211. X*** 77,82
  212. X  Log=''
  213. X  Header=''
  214. X  sitename=''
  215. X  orgname=''
  216. X  isadmin=''
  217. X  newsadmin=''
  218. X
  219. X--- 77,83 -----
  220. X  Log=''
  221. X  Header=''
  222. X  sitename=''
  223. X+ domain=''
  224. X  orgname=''
  225. X  isadmin=''
  226. X  newsadmin=''
  227. X***************
  228. X*** 117,122
  229. X  phostname=''
  230. X  hostcmd=''
  231. X  norelay=''
  232. X  CONFIG=''
  233. X  
  234. X  echo "Beginning of configuration questions for rn kit."
  235. X
  236. X--- 118,127 -----
  237. X  phostname=''
  238. X  hostcmd=''
  239. X  norelay=''
  240. X+ isrrn=''
  241. X+ rrnserver=''
  242. X+ serverfile=''
  243. X+ NNTPSRC=''
  244. X  CONFIG=''
  245. X  
  246. X  echo "Beginning of configuration questions for rn kit."
  247. X***************
  248. X*** 681,686
  249. X      hostcmd=''
  250. X  done
  251. X  
  252. X  : get organizaton name
  253. X  longshots='/usr/src/new /usr/src/local /usr/local/src'
  254. X  case "$orgname" in
  255. X
  256. X--- 686,725 -----
  257. X      hostcmd=''
  258. X  done
  259. X  
  260. X+ : try to deal with domains
  261. X+ $cat << 'EOH'
  262. X+ 
  263. X+ Please enter your domain name.  This will be used in conjunction
  264. X+ with the site name for return addresses on news articles and
  265. X+ mail.  If you use the 4.3ism of having your domain in your
  266. X+ hostname, all the posting programs will figure this out on the
  267. X+ fly, so don't worry.
  268. X+ 
  269. X+ Examples of some valid domains:
  270. X+ 
  271. X+     uucp
  272. X+     arpa
  273. X+     berkeley.edu
  274. X+     nsa.gov
  275. X+ 
  276. X+ EOH
  277. X+ 
  278. X+ dflt="uucp"
  279. X+ $echo $n "Your domain: [$dflt] $c"
  280. X+ . myread
  281. X+ case "$ans" in
  282. X+ '') domain="$dflt";;
  283. X+ *)  domain="$ans" ;;
  284. X+ esac
  285. X+ 
  286. X+ if $test $portable = "undef" ; then
  287. X+     case $sitename in
  288. X+     *.*)    ;;
  289. X+     *)    sitename=$sitename.$domain
  290. X+         ;;
  291. X+     esac
  292. X+ fi
  293. X+ 
  294. X  : get organizaton name
  295. X  longshots='/usr/src/new /usr/src/local /usr/local/src'
  296. X  case "$orgname" in
  297. X***************
  298. X*** 769,774
  299. X      blurfl*) ;;
  300. X      *) $echo "Directory $libexp not found";;
  301. X      esac
  302. X      echo $n "Where is your news library (~name okay)? [$dflt] $c"
  303. X      . myread
  304. X      case "$ans" in
  305. X
  306. X--- 808,817 -----
  307. X      blurfl*) ;;
  308. X      *) $echo "Directory $libexp not found";;
  309. X      esac
  310. X+     echo "(If you are building this as rrn, it is a good idea"
  311. X+     echo "to make your news library directory the same as where the rn"
  312. X+     echo "library directory is, usually /usr/local/lib/rn)"
  313. X+     echo " "
  314. X      echo $n "Where is your news library (~name okay)? [$dflt] $c"
  315. X      . myread
  316. X      case "$ans" in
  317. X***************
  318. X*** 1281,1287
  319. X      fi
  320. X  fi
  321. X  
  322. X! : locate spool directory
  323. X  case "$spool" in
  324. X  '')
  325. X      dflt=/usr/spool/news
  326. X
  327. X--- 1324,1422 -----
  328. X      fi
  329. X  fi
  330. X  
  331. X! : locate spool directory and check if rrn
  332. X! case "$isrrn" in
  333. X! define)
  334. X!     dflt="y";;
  335. X! *)
  336. X!     dflt="n";;
  337. X! esac
  338. X! isrrn=''
  339. X! while $test -z "$isrrn" ; do
  340. X!     $echo " "
  341. X!     $echo $n "Do you want this built as remote rn (rrn)? [$dflt] $c"
  342. X!     . myread
  343. X!     case "$ans" in
  344. X!     '') ans="$dflt";;
  345. X!     esac
  346. X!     case "$ans" in
  347. X!     n*)
  348. X!     isrrn=undef;;
  349. X!     y*)
  350. X!     isrrn=define
  351. X!     spool=/tmp
  352. X!     $echo "net.foobar 00001 00001 y" > .falseactive
  353. X! 
  354. X!     case "$serverfile" in
  355. X!     '')  dflt="no default" ;;
  356. X!     *)   dflt="$serverfile";;
  357. X!     esac
  358. X! 
  359. X!     $cat <<'EOM'
  360. X! 
  361. X! rrn determines the machine to use as a news server by two means:
  362. X! 
  363. X!     1. It examines the environment variable NNTPSERVER for
  364. X!        a machine name; this allows users to use server machines
  365. X!        other than the default.
  366. X! 
  367. X!     2. It looks in a file which contains the name of a server
  368. X!        machine.
  369. X! 
  370. X! You must create the file mentioned in (2), above.  Simply put the name
  371. X! of the machine you wish to use as your news server in this file.
  372. X! If you really want, you can use # for comments and blank lines in
  373. X! this file as well.
  374. X! 
  375. X! EOM
  376. X! 
  377. X!     ans=''
  378. X!     while $test -z "$ans" ; do
  379. X!     $echo $n "Enter the name of the news server file: [$dflt] $c"
  380. X!     . myread
  381. X!     done
  382. X!     serverfile="$ans"
  383. X! 
  384. X!     case "$rrnserver" in
  385. X!     '')  dflt="no default" ;;
  386. X!     *)   dflt="$rrnserver";;
  387. X!     esac
  388. X! 
  389. X!     case "$NNTPSRC" in
  390. X!     '') dflt="no default";;
  391. X!     *)  dflt="$NNTPSRC";;
  392. X!     esac
  393. X! 
  394. X!     ans='blurfl/dyick'
  395. X!     while $test ! -d "$ans"; do
  396. X!         $echo $n "Enter the pathname of the NNTP source directory: [$dflt] $c"
  397. X!         . myread
  398. X!         case "$ans" in
  399. X!         '') ans="$dflt";;
  400. X!         esac
  401. X!         ans=`filexp "$ans"`
  402. X!         if $test ! -r $ans/common/nntp.h ; then
  403. X!         ans='blurfl/dyick'
  404. X!         fi
  405. X!     done
  406. X!     NNTPSRC="$ans"
  407. X! cat > server.h <<EOF_SERVE
  408. X! #ifdef SERVER
  409. X! 
  410. X! EXT    char    *getserverbyfile();
  411. X! EXT    int    server_init();
  412. X! EXT    void    put_server();
  413. X! EXT    int    get_server();
  414. X! EXT    void    close_server();
  415. X! 
  416. X! #include "$NNTPSRC/common/nntp.h"
  417. X! #endif
  418. X! EOF_SERVE
  419. X! 
  420. X!     esac
  421. X! 
  422. X! done
  423. X! 
  424. X  case "$spool" in
  425. X  '')
  426. X      dflt=/usr/spool/news
  427. X***************
  428. X*** 1288,1294
  429. X      ;;
  430. X  *)  dflt="$spool";;
  431. X  esac
  432. X! ans='blurfl/dyick'
  433. X  while $test ! -d $ans; do
  434. X      $echo " "
  435. X      case "$ans" in
  436. X
  437. X--- 1423,1432 -----
  438. X      ;;
  439. X  *)  dflt="$spool";;
  440. X  esac
  441. X! case "$isrrn" in
  442. X! define)  ans=/tmp;;
  443. X! *) ans='blurfl/dyick';;
  444. X! esac
  445. X  while $test ! -d $ans; do
  446. X      $echo " "
  447. X      case "$ans" in
  448. X***************
  449. X*** 1322,1328
  450. X      ;;
  451. X  *)  dflt="$active";;
  452. X  esac
  453. X! myactive='blurfl/dyick'
  454. X  while $test ! -f "$myactive"; do
  455. X      $echo " "
  456. X      case "$myactive" in
  457. X
  458. X--- 1460,1469 -----
  459. X      ;;
  460. X  *)  dflt="$active";;
  461. X  esac
  462. X! case "$isrrn" in
  463. X! define) myactive=.falseactive;;
  464. X! *) myactive='blurfl/dyick'
  465. X! esac
  466. X  while $test ! -f "$myactive"; do
  467. X      $echo " "
  468. X      case "$myactive" in
  469. X***************
  470. X*** 1799,1804
  471. X  Log='$Log'
  472. X  Header='$Header'
  473. X  sitename='$sitename'
  474. X  orgname='$orgname'
  475. X  isadmin='$isadmin'
  476. X  newsadmin='$newsadmin'
  477. X
  478. X--- 1940,1946 -----
  479. X  Log='$Log'
  480. X  Header='$Header'
  481. X  sitename='$sitename'
  482. X+ domain='$domain'
  483. X  orgname='$orgname'
  484. X  isadmin='$isadmin'
  485. X  newsadmin='$newsadmin'
  486. X***************
  487. X*** 1839,1844
  488. X  phostname='$phostname'
  489. X  hostcmd='$hostcmd'
  490. X  norelay='$norelay'
  491. X  CONFIG=true
  492. X  EOT
  493. X  
  494. X
  495. X--- 1981,1989 -----
  496. X  phostname='$phostname'
  497. X  hostcmd='$hostcmd'
  498. X  norelay='$norelay'
  499. X+ isrrn='$isrrn'
  500. X+ rrnserver='$rrnserver'
  501. X+ NNTPSRC='$NNTPSRC'
  502. X  CONFIG=true
  503. X  EOT
  504. X  
  505. X***************
  506. X*** 1926,1931
  507. X  #$douname    DOUNAME        /* do we have a uname function? */
  508. X  #$phostname    PHOSTNAME "$hostcmd"    /* how to get host name with popen */
  509. X  #$norelay     NORELAY         /* 2.10.3 doesn't have Relay-Version line */
  510. X  EOT
  511. X  
  512. X  CONFIG=true
  513. X
  514. X--- 2071,2079 -----
  515. X  #$douname    DOUNAME        /* do we have a uname function? */
  516. X  #$phostname    PHOSTNAME "$hostcmd"    /* how to get host name with popen */
  517. X  #$norelay     NORELAY         /* 2.10.3 doesn't have Relay-Version line */
  518. X+ #$isrrn         SERVER          /* rrn server code */
  519. X+ #$isrrn SERVER_HOST     "$rrnserver"
  520. X+ #$isrrn SERVER_FILE    "$serverfile"
  521. X  EOT
  522. X  
  523. X  CONFIG=true
  524. END_OF_FILE
  525. if test 6499 -ne `wc -c <'./rrnpatches/Configure.pat'`; then
  526.     echo shar: \"'./rrnpatches/Configure.pat'\" unpacked with wrong size!
  527. fi
  528. # end of './rrnpatches/Configure.pat'
  529. fi
  530. if test -f './rrnpatches/rcstuff.c.pat' -a "${1}" != "-c" ; then 
  531.   echo shar: Will not clobber existing file \"'./rrnpatches/rcstuff.c.pat'\"
  532. else
  533. echo shar: Extracting \"'./rrnpatches/rcstuff.c.pat'\" \(6131 characters\)
  534. sed "s/^X//" >'./rrnpatches/rcstuff.c.pat' <<'END_OF_FILE'
  535. X*** rn/rcstuff.c    Sun Mar 15 19:54:20 1987
  536. X--- rrn/rcstuff.c    Fri May 29 09:33:43 1987
  537. X***************
  538. X*** 31,36
  539. X  #include "intrp.h"
  540. X  #include "only.h"
  541. X  #include "rcln.h"
  542. X  #include "INTERN.h"
  543. X  #include "rcstuff.h"
  544. X  
  545. X
  546. X--- 31,37 -----
  547. X  #include "intrp.h"
  548. X  #include "only.h"
  549. X  #include "rcln.h"
  550. X+ #include "server.h"
  551. X  #include "INTERN.h"
  552. X  #include "rcstuff.h"
  553. X  
  554. X***************
  555. X*** 53,58
  556. X      register bool foundany = FALSE;
  557. X      char *some_buf;
  558. X      long length;
  559. X  
  560. X  #ifdef HASHNG
  561. X      for (i=0; i<HASHSIZ; i++)
  562. X
  563. X--- 54,62 -----
  564. X      register bool foundany = FALSE;
  565. X      char *some_buf;
  566. X      long length;
  567. X+ #ifdef SERVER
  568. X+     char *cp;
  569. X+ #endif SERVER
  570. X  
  571. X  #ifdef HASHNG
  572. X      for (i=0; i<HASHSIZ; i++)
  573. X***************
  574. X*** 61,66
  575. X  
  576. X      /* make filenames */
  577. X  
  578. X      rcname = savestr(filexp(RCNAME));
  579. X      rctname = savestr(filexp(RCTNAME));
  580. X      rcbname = savestr(filexp(RCBNAME));
  581. X
  582. X--- 65,79 -----
  583. X  
  584. X      /* make filenames */
  585. X  
  586. X+ #ifdef SERVER
  587. X+ 
  588. X+     if (cp = getenv("NEWSRC"))
  589. X+     rcname = savestr(filexp(cp));
  590. X+     else
  591. X+     rcname = savestr(filexp(RCNAME));
  592. X+ 
  593. X+ #else not SERVER
  594. X+ 
  595. X      rcname = savestr(filexp(RCNAME));
  596. X  
  597. X  #endif SERVER
  598. X***************
  599. X*** 62,67
  600. X      /* make filenames */
  601. X  
  602. X      rcname = savestr(filexp(RCNAME));
  603. X      rctname = savestr(filexp(RCTNAME));
  604. X      rcbname = savestr(filexp(RCBNAME));
  605. X      softname = savestr(filexp(SOFTNAME));
  606. X
  607. X--- 75,83 -----
  608. X  #else not SERVER
  609. X  
  610. X      rcname = savestr(filexp(RCNAME));
  611. X+ 
  612. X+ #endif SERVER
  613. X+ 
  614. X      rctname = savestr(filexp(RCTNAME));
  615. X      rcbname = savestr(filexp(RCBNAME));
  616. X      softname = savestr(filexp(SOFTNAME));
  617. X***************
  618. X*** 224,229
  619. X  /* returns TRUE if found or added, FALSE if not. */
  620. X  /* assumes that we are chdir'ed to SPOOL */
  621. X  
  622. X  bool
  623. X  get_ng(what,do_reloc)
  624. X  char *what;
  625. X
  626. X--- 240,249 -----
  627. X  /* returns TRUE if found or added, FALSE if not. */
  628. X  /* assumes that we are chdir'ed to SPOOL */
  629. X  
  630. X+ #ifdef SERVER
  631. X+ static int addnewbydefault = 0;
  632. X+ #endif SERVER
  633. X+ 
  634. X  bool
  635. X  get_ng(what,do_reloc)
  636. X  char *what;
  637. X***************
  638. X*** 231,236
  639. X  {
  640. X      char *ntoforget;
  641. X      char promptbuf[128];
  642. X  
  643. X  #ifdef VERBOSE
  644. X      IF(verbose)
  645. X
  646. X--- 251,259 -----
  647. X  {
  648. X      char *ntoforget;
  649. X      char promptbuf[128];
  650. X+ #ifdef SERVER
  651. X+     char ser_line[256];
  652. X+ #endif SERVER
  653. X  
  654. X  #ifdef VERBOSE
  655. X      IF(verbose)
  656. X***************
  657. X*** 248,253
  658. X      set_ngname(what);
  659. X      ng = find_ng(ngname);
  660. X      if (ng == nextrcline) {        /* not in .newsrc? */
  661. X      if ((softptr[ng] = findact(buf,ngname,strlen(ngname),0L)) < 0 ) {
  662. X          dingaling();
  663. X  #ifdef VERBOSE
  664. X
  665. X--- 271,291 -----
  666. X      set_ngname(what);
  667. X      ng = find_ng(ngname);
  668. X      if (ng == nextrcline) {        /* not in .newsrc? */
  669. X+ 
  670. X+ #ifdef SERVER
  671. X+     sprintf(ser_line, "GROUP %s", ngname);
  672. X+     put_server(ser_line);
  673. X+     if (get_server(ser_line, sizeof(ser_line)) < 0) {
  674. X+         fprintf(stderr, "rrn: Unexpected close of server socket.\n");
  675. X+         finalize(1);
  676. X+     }
  677. X+     if (*ser_line != CHAR_OK) {
  678. X+         if (atoi(ser_line) != ERR_NOGROUP) {
  679. X+         fprintf(stderr, "Server response to GROUP %s:\n%s\n",
  680. X+             ngname, ser_line);
  681. X+         }
  682. X+ #else not SERVER
  683. X+ 
  684. X      if ((softptr[ng] = findact(buf,ngname,strlen(ngname),0L)) < 0 ) {
  685. X  
  686. X  #endif SERVER
  687. X***************
  688. X*** 249,254
  689. X      ng = find_ng(ngname);
  690. X      if (ng == nextrcline) {        /* not in .newsrc? */
  691. X      if ((softptr[ng] = findact(buf,ngname,strlen(ngname),0L)) < 0 ) {
  692. X          dingaling();
  693. X  #ifdef VERBOSE
  694. X          IF(verbose)
  695. X
  696. X--- 287,295 -----
  697. X  #else not SERVER
  698. X  
  699. X      if ((softptr[ng] = findact(buf,ngname,strlen(ngname),0L)) < 0 ) {
  700. X+ 
  701. X+ #endif SERVER
  702. X+ 
  703. X          dingaling();
  704. X  #ifdef VERBOSE
  705. X          IF(verbose)
  706. X***************
  707. X*** 261,266
  708. X          sleep(2);
  709. X          return FALSE;
  710. X      }
  711. X  #ifdef VERBOSE
  712. X      IF(verbose)
  713. X          sprintf(promptbuf,"\nNewsgroup %s not in .newsrc--add? [yn] ",ngname);
  714. X
  715. X--- 302,314 -----
  716. X          sleep(2);
  717. X          return FALSE;
  718. X      }
  719. X+ #ifdef SERVER
  720. X+     if (addnewbydefault) {
  721. X+         printf("(Adding %s to end of your .newsrc)\n", ngname);
  722. X+             ng = add_newsgroup(ngname);
  723. X+             do_reloc = FALSE;
  724. X+     } else {
  725. X+ #endif SERVER
  726. X  #ifdef VERBOSE
  727. X      IF(verbose)
  728. X          sprintf(promptbuf,"\nNewsgroup %s not in .newsrc--add? [yn] ",ngname);
  729. X***************
  730. X*** 296,301
  731. X          ng = add_newsgroup(ngname);
  732. X          do_reloc = FALSE;
  733. X      }
  734. X      else {
  735. X          fputs(hforhelp,stdout) FLUSH;
  736. X          settle_down();
  737. X
  738. X--- 344,359 -----
  739. X          ng = add_newsgroup(ngname);
  740. X          do_reloc = FALSE;
  741. X      }
  742. X+ #ifdef SERVER
  743. X+     else if (*buf == 'Y') {
  744. X+         fputs(
  745. X+     "(I'll add all new newsgroups to the end of your .newsrc.)\n", stdout);
  746. X+         addnewbydefault = 1;
  747. X+         printf("(Adding %s to end of your .newsrc)\n", ngname);
  748. X+         ng = add_newsgroup(ngname);
  749. X+         do_reloc = FALSE;
  750. X+     }
  751. X+ #endif SERVER
  752. X      else {
  753. X          fputs(hforhelp,stdout) FLUSH;
  754. X          settle_down();
  755. X***************
  756. X*** 301,306
  757. X          settle_down();
  758. X          goto reask_add;
  759. X      }
  760. X      }
  761. X      else if (rcchar[ng] == NEGCHAR) {    /* unsubscribed? */
  762. X  #ifdef VERBOSE
  763. X
  764. X--- 359,367 -----
  765. X          settle_down();
  766. X          goto reask_add;
  767. X      }
  768. X+ #ifdef SERVER
  769. X+       }
  770. X+ #endif SERVER
  771. X      }
  772. X      else if (rcchar[ng] == NEGCHAR) {    /* unsubscribed? */
  773. X  #ifdef VERBOSE
  774. X***************
  775. X*** 453,458
  776. X      if (newng < 0) {
  777. X        reask_reloc:
  778. X      unflush_output();        /* disable any ^O in effect */
  779. X  #ifdef VERBOSE
  780. X      IF(verbose)
  781. X          printf("\nPut newsgroup where? [%s] ", dflt);
  782. X
  783. X--- 514,525 -----
  784. X      if (newng < 0) {
  785. X        reask_reloc:
  786. X      unflush_output();        /* disable any ^O in effect */
  787. X+ #ifdef SERVER
  788. X+     if (addnewbydefault) {
  789. X+         buf[0] = '$';
  790. X+         buf[1] = '\0';
  791. X+     } else {
  792. X+ #endif SERVER
  793. X  #ifdef VERBOSE
  794. X      IF(verbose)
  795. X          printf("\nPut newsgroup where? [%s] ", dflt);
  796. X***************
  797. X*** 465,470
  798. X        reinp_reloc:
  799. X      eat_typeahead();
  800. X      getcmd(buf);
  801. X      if (errno || *buf == '\f') {
  802. X                  /* if return from stop signal */
  803. X          goto reask_reloc;    /* give them a prompt again */
  804. X
  805. X--- 532,540 -----
  806. X        reinp_reloc:
  807. X      eat_typeahead();
  808. X      getcmd(buf);
  809. X+ #ifdef SERVER
  810. X+     }
  811. X+ #endif SERVER
  812. X      if (errno || *buf == '\f') {
  813. X                  /* if return from stop signal */
  814. X          goto reask_reloc;    /* give them a prompt again */
  815. END_OF_FILE
  816. if test 6131 -ne `wc -c <'./rrnpatches/rcstuff.c.pat'`; then
  817.     echo shar: \"'./rrnpatches/rcstuff.c.pat'\" unpacked with wrong size!
  818. fi
  819. # end of './rrnpatches/rcstuff.c.pat'
  820. fi
  821. if test -f './server/serve.c' -a "${1}" != "-c" ; then 
  822.   echo shar: Will not clobber existing file \"'./server/serve.c'\"
  823. else
  824. echo shar: Extracting \"'./server/serve.c'\" \(6497 characters\)
  825. sed "s/^X//" >'./server/serve.c' <<'END_OF_FILE'
  826. X#ifndef lint
  827. static char    *sccsid = "@(#)serve.c    1.29    (Berkeley) 2/6/88";
  828. X#endif
  829. X
  830. X/*
  831. X * Main server routine
  832. X */
  833. X
  834. X#include "common.h"
  835. X#include <signal.h>
  836. X#ifdef USG
  837. X#include <sys/times.h>
  838. X#else
  839. X#include <sys/time.h>
  840. X#endif
  841. X
  842. X#ifdef LOG
  843. X# ifndef USG
  844. X#  include <sys/resource.h>
  845. X# endif not USG
  846. X#endif
  847. X
  848. extern    int    ahbs(), group(), help(), ihave();
  849. extern    int    list(), newgroups(), newnews(), nextlast(), post();
  850. extern    int    slave(), stat(), xhdr();
  851. X
  852. static struct cmdent {
  853. X    char    *cmd_name;
  854. X    int    (*cmd_fctn)();
  855. X} cmdtbl[] = {
  856. X    "article",    ahbs,
  857. X    "body",        ahbs,
  858. X    "group",    group,
  859. X    "head",        ahbs,
  860. X    "help",        help,
  861. X    "ihave",    ihave,
  862. X    "last",        nextlast,
  863. X    "list",        list,
  864. X    "newgroups",    newgroups,
  865. X    "newnews",    newnews,
  866. X    "next",        nextlast,
  867. X    "post",        post,
  868. X    "slave",    slave,
  869. X    "stat",        ahbs,
  870. X#ifdef XHDR
  871. X    "xhdr",        xhdr,
  872. X#endif XHDR
  873. X};
  874. X#define NUMCMDS (sizeof(cmdtbl) / sizeof(struct cmdent))
  875. X
  876. X
  877. X/*
  878. X * serve -- given a connection on stdin/stdout, serve
  879. X *    a client, executing commands until the client
  880. X *    says goodbye.
  881. X *
  882. X *    Parameters:    None.
  883. X *
  884. X *    Returns:    Exits.
  885. X *
  886. X *    Side effects:    Talks to client, does a lot of
  887. X *            stuff.
  888. X */
  889. X
  890. serve()
  891. X{
  892. X    char        line[NNTP_STRLEN];
  893. X    char        host[MAXHOSTNAMELEN];
  894. X    char        gdbuf[MAXBUFLEN];
  895. X    char        **argp;
  896. X    char        *timeptr, *cp;
  897. X    int        argnum, i;
  898. X    double        Tstart, Tfinish;
  899. X    double        user, sys;
  900. X#ifdef USG
  901. X    time_t        start, finish;
  902. X#else not USG
  903. X    struct timeval    start, finish;
  904. X#endif not USG
  905. X    extern char    *ctime();
  906. X#ifdef POSTER
  907. X    struct passwd    *pp;
  908. X#endif
  909. X#ifdef LOG
  910. X# ifdef USG
  911. X    struct tms    cpu;
  912. X# else not USG
  913. X    struct rusage    me, kids;
  914. X# endif not USG
  915. X# ifdef TIMEOUT
  916. X    void        timeout();
  917. X# endif
  918. X    
  919. X    grps_acsd = arts_acsd = 0;
  920. X#endif
  921. X
  922. X    /* Not all systems pass fd's 1 and 2 from inetd */
  923. X
  924. X    (void) close(1);
  925. X    (void) close(2);
  926. X    (void) dup(0);
  927. X    (void) dup(0);
  928. X
  929. X    /* If we're ALONE, then we've already opened syslog */
  930. X
  931. X#ifndef ALONE
  932. X# ifdef SYSLOG
  933. X#  ifdef BSD_42
  934. X    openlog("nntpd", LOG_PID);
  935. X#  else
  936. X    openlog("nntpd", LOG_PID, SYSLOG);
  937. X#  endif
  938. X# endif
  939. X#endif
  940. X
  941. X#ifdef ALONE
  942. X#ifndef USG
  943. X    (void) signal(SIGCHLD, SIG_IGN);
  944. X#endif not USG
  945. X#endif
  946. X
  947. X    /* Ignore SIGPIPE, since we'll see closed connections with read */
  948. X
  949. X    (void) signal(SIGPIPE, SIG_IGN);
  950. X
  951. X    /* Get permissions and see if we can talk to this client */
  952. X
  953. X    host_access(&canread, &canpost, &canxfer, gdbuf);
  954. X
  955. X    if (gethostname(host, sizeof(host)) < 0)
  956. X        (void) strcpy(host, "Amnesiac");
  957. X
  958. X    if (!canread && !canxfer) {
  959. X        printf("%d %s NNTP server can't talk to you.  Goodbye.\r\n",
  960. X            ERR_ACCESS, host);
  961. X        (void) fflush(stdout);
  962. X#ifdef LOG
  963. X        syslog(LOG_INFO, "%s refused connection", hostname);
  964. X#endif
  965. X        exit(1);
  966. X    }
  967. X
  968. X    /* If we can talk, proceed with initialization */
  969. X
  970. X    ngpermcount = get_nglist(&ngpermlist, gdbuf);
  971. X
  972. X#ifdef POSTER
  973. X    pp = getpwnam(POSTER);
  974. X    if (pp != NULL) {
  975. X        uid_poster = pp->pw_uid;
  976. X        gid_poster = pp->pw_gid;
  977. X    } else
  978. X#endif
  979. X        uid_poster = gid_poster = 0;
  980. X
  981. X#ifndef FASTFORK
  982. X    num_groups = 0;
  983. X    num_groups = read_groups();    /* Read in the active file */
  984. X#else
  985. X    signal(SIGALRM, SIG_IGN);    /* Children don't deal with */
  986. X                    /* these things */
  987. X#endif
  988. X
  989. X    art_fp = NULL;
  990. X    argp = (char **) NULL;        /* for first time */
  991. X
  992. X#ifdef USG
  993. X    (void) time(&start);
  994. X    Tstart = (double) start;
  995. X    timeptr = ctime(&start);
  996. X#else not USG
  997. X    (void) gettimeofday(&start, (struct timezone *)NULL);
  998. X    Tstart = (double) start.tv_sec - ((double)start.tv_usec)/1000000.0;
  999. X    timeptr = ctime(&start.tv_sec);
  1000. X#endif not USG
  1001. X    if ((cp = index(timeptr, '\n')) != NULL)
  1002. X        *cp = '\0';
  1003. X    else
  1004. X        timeptr = "Unknown date";
  1005. X
  1006. X    printf("%d %s NNTP server version %s ready at %s (%s).\r\n",
  1007. X        canpost ? OK_CANPOST : OK_NOPOST,
  1008. X        host, nntp_version,
  1009. X        timeptr,
  1010. X        canpost ? "posting ok" : "no posting");
  1011. X    (void) fflush(stdout);
  1012. X
  1013. X    /*
  1014. X     * Now get commands one at a time and execute the
  1015. X     * appropriate routine to deal with them.
  1016. X     */
  1017. X
  1018. X#ifdef TIMEOUT
  1019. X    (void) signal(SIGALRM, timeout);
  1020. X    (void) alarm(TIMEOUT);
  1021. X#endif TIMEOUT
  1022. X
  1023. X    while (fgets(line, sizeof(line), stdin) != NULL) {
  1024. X#ifdef TIMEOUT
  1025. X        (void) alarm(0);
  1026. X#endif TIMEOUT
  1027. X
  1028. X        cp = index(line, '\r');        /* Zap CR-LF */
  1029. X        if (cp != NULL)
  1030. X            *cp = '\0';
  1031. X        else {
  1032. X            cp = index(line, '\n');
  1033. X            if (cp != NULL)
  1034. X                *cp = '\0';
  1035. X        }
  1036. X
  1037. X        if ((argnum = parsit(line, &argp)) == 0)
  1038. X            continue;        /* Null command */
  1039. X        else {
  1040. X            for (i = 0; i < NUMCMDS; ++i)
  1041. X                if (!strcasecmp(cmdtbl[i].cmd_name, argp[0]))
  1042. X                    break;
  1043. X            if (i < NUMCMDS)
  1044. X                (*cmdtbl[i].cmd_fctn)(argnum, argp);
  1045. X            else {
  1046. X                if (!strcasecmp(argp[0], "quit"))
  1047. X                    break;
  1048. X#ifdef LOG
  1049. X                syslog(LOG_INFO, "%s unrecognized %s",
  1050. X                    hostname,
  1051. X                    line);
  1052. X#endif
  1053. X                printf("%d Command unrecognized.\r\n",
  1054. X                    ERR_COMMAND);
  1055. X                (void) fflush(stdout);
  1056. X            }
  1057. X        }
  1058. X#ifdef TIMEOUT
  1059. X        (void) alarm(TIMEOUT);
  1060. X#endif TIMEOUT
  1061. X    }
  1062. X
  1063. X    printf("%d %s closing connection.  Goodbye.\r\n", OK_GOODBYE, host);
  1064. X    (void) fflush(stdout);
  1065. X
  1066. X
  1067. X#ifdef LOG
  1068. X    if (ferror(stdout))
  1069. X        syslog(LOG_ERR, "%s disconnect: %m", hostname);
  1070. X
  1071. X#ifdef USG
  1072. X    (void) time(&finish);
  1073. X    Tfinish = (double) finish;
  1074. X
  1075. X#ifndef HZ
  1076. X#define    HZ    60.0    /* typical system clock ticks - param.h */
  1077. X#endif not HZ
  1078. X
  1079. X    (void) times(&cpu);
  1080. X    user = (double)(cpu.tms_utime + cpu.tms_cutime) / HZ;
  1081. X    sys  = (double)(cpu.tms_stime + cpu.tms_cstime) / HZ;
  1082. X#else not USG
  1083. X    (void) gettimeofday(&finish, (struct timezone *)NULL);
  1084. X    Tfinish = (double) finish.tv_sec - ((double)finish.tv_usec)/1000000.0;
  1085. X
  1086. X    (void) getrusage(RUSAGE_SELF, &me);
  1087. X    (void) getrusage(RUSAGE_CHILDREN, &kids);
  1088. X
  1089. X    user = (double) me.ru_utime.tv_sec + me.ru_utime.tv_usec/1000000.0 +
  1090. X        kids.ru_utime.tv_sec + kids.ru_utime.tv_usec/1000000.0;
  1091. X    sys = (double) me.ru_stime.tv_sec + me.ru_stime.tv_usec/1000000.0 +
  1092. X        kids.ru_stime.tv_sec + kids.ru_stime.tv_usec/1000000.0;
  1093. X#endif not USG
  1094. X    if (grps_acsd)
  1095. X        syslog(LOG_INFO, "%s exit %d articles %d groups",
  1096. X            hostname, arts_acsd, grps_acsd);
  1097. X    if (nn_told)
  1098. X        syslog(LOG_INFO, "%s newnews_stats told %d took %d",
  1099. X            hostname, nn_told, nn_took);
  1100. X    if (ih_accepted || ih_rejected || ih_failed)
  1101. X        syslog(LOG_INFO,
  1102. X            "%s ihave_stats accepted %d rejected %d failed %d",
  1103. X            hostname,
  1104. X            ih_accepted,
  1105. X            ih_rejected,
  1106. X            ih_failed);
  1107. X    (void) sprintf(line, "user %.1f system %.1f elapsed %.1f",
  1108. X        user, sys, Tfinish - Tstart);
  1109. X    syslog(LOG_INFO, "%s times %s", hostname, line);
  1110. X#endif LOG
  1111. X
  1112. X#ifdef PROFILE
  1113. X    profile();
  1114. X#endif
  1115. X
  1116. X    exit(0);
  1117. X}
  1118. X
  1119. X
  1120. X#ifdef TIMEOUT
  1121. X/*
  1122. X * No activity for TIMEOUT seconds, so print an error message
  1123. X * and close the connection.
  1124. X */
  1125. X
  1126. void
  1127. timeout()
  1128. X{
  1129. X    printf("%d Timeout after %d seconds, closing connection.\r\n",
  1130. X        ERR_FAULT, TIMEOUT);
  1131. X    (void) fflush(stdout);
  1132. X
  1133. X#ifdef LOG
  1134. X    syslog(LOG_ERR, "%s timeout", hostname);
  1135. X#endif LOG
  1136. X
  1137. X    exit(1);
  1138. X}
  1139. X#endif TIMEOUT
  1140. END_OF_FILE
  1141. if test 6497 -ne `wc -c <'./server/serve.c'`; then
  1142.     echo shar: \"'./server/serve.c'\" unpacked with wrong size!
  1143. fi
  1144. # end of './server/serve.c'
  1145. fi
  1146. if test -f './server/subnet.c' -a "${1}" != "-c" ; then 
  1147.   echo shar: Will not clobber existing file \"'./server/subnet.c'\"
  1148. else
  1149. echo shar: Extracting \"'./server/subnet.c'\" \(6358 characters\)
  1150. sed "s/^X//" >'./server/subnet.c' <<'END_OF_FILE'
  1151. X#ifndef lint
  1152. static    char    *sccsid = "@(#)subnet.c    1.5    (Berkeley) 1/4/88";
  1153. X#endif
  1154. X
  1155. X#include "../common/conf.h"
  1156. X
  1157. X#ifdef SUBNET
  1158. X
  1159. X#include <sys/types.h>
  1160. X#include <sys/socket.h>
  1161. X#include <netinet/in.h>
  1162. X#ifndef NETMASK
  1163. X#include <net/if.h>
  1164. X#endif
  1165. X#include <sys/ioctl.h>
  1166. X
  1167. X/*
  1168. X * The following routines provide a general interface for
  1169. X * subnet support.  Like the library function "inet_netof",
  1170. X * which returns the standard (i.e., non-subnet) network
  1171. X * portion of an internet address, "inet_snetof" returns
  1172. X * the subnetwork portion -- if there is one.  If there
  1173. X * isn't, it returns 0.
  1174. X *
  1175. X * Subnets, under 4.3, are specific to a given set of
  1176. X * machines -- right down to the network interfaces.
  1177. X * Because of this, the function "getifconf" must be
  1178. X * called first.  This routine builds a table listing
  1179. X * all the (internet) interfaces present on a machine,
  1180. X * along with their subnet masks.  Then when inet_snetof
  1181. X * is called, it can quickly scan this table.
  1182. X *
  1183. X * Unfortunately, there "ain't no graceful way" to handle
  1184. X * certain situations.  For example, the kernel permits
  1185. X * arbitrary subnet bits -- that is, you could have a
  1186. X * 22 bit network field and a 10 bit subnet field.
  1187. X * However, due to braindamage at the user level, in
  1188. X * such sterling routines as getnetbyaddr, you need to
  1189. X * have a subnet mask which is an even multiple of 8.
  1190. X * Unless you are running with class C subnets, in which
  1191. X * case it should be a multiple of 4.  Because of this rot,
  1192. X * if you have non-multiples of 4 bits of subnet, you should
  1193. X * define DAMAGED_NETMASK when you compile.  This will round
  1194. X * things off to a multiple of 8 bits.
  1195. X *
  1196. X * Finally, you may want subnet support even if your system doesn't
  1197. X * support the ioctls to get subnet mask information.  If you want
  1198. X * such a thing, you can define NETMASK to be a constant that is
  1199. X * the subnet mask for your network.
  1200. X *
  1201. X * And don't *even* get me started on how the definitions of the inet_foo()
  1202. X * routines changed between 4.2 and 4.3, making internet addresses
  1203. X * be unsigned long vs. struct in_addr.  Don't blame me if this
  1204. X * won't lint...
  1205. X */
  1206. X
  1207. X/*
  1208. X * One structure for each interface, containing
  1209. X * the network number and subnet mask, stored in HBO.
  1210. X */
  1211. struct in_if {
  1212. X    u_long    i_net;        /* Network number, shifted right */
  1213. X    u_long    i_subnetmask;    /* Subnet mask for this if */
  1214. X    int    i_bitshift;    /* How many bits right for outside */
  1215. X};
  1216. X
  1217. X/*
  1218. X * Table (eventually, once we malloc) of
  1219. X * internet interface subnet informaiton.
  1220. X */
  1221. static    struct in_if    *in_ifsni;
  1222. X
  1223. static    int        if_count;
  1224. X
  1225. X/*
  1226. X * Get the network interface configuration,
  1227. X * and squirrel away the network numbers and
  1228. X * subnet masks of each interface.  Return
  1229. X * number of interfaces found, or -1 on error.
  1230. X * N.B.: don't call this more than once...
  1231. X */
  1232. X
  1233. getifconf()
  1234. X{
  1235. X#ifndef NETMASK
  1236. X    register int    i, j;
  1237. X    int        s;
  1238. X    struct ifconf    ifc;
  1239. X    char        buf[1024];
  1240. X    register struct ifreq    *ifr;
  1241. X    u_long        inet_netof();
  1242. X    u_long        addr;
  1243. X
  1244. X    /*
  1245. X     * Find out how many interfaces we have, and malloc
  1246. X     * room for information about each one.
  1247. X     */
  1248. X
  1249. X    s = socket(AF_INET, SOCK_DGRAM, 0);
  1250. X    if (s < 0)
  1251. X        return (-1);
  1252. X
  1253. X    ifc.ifc_buf = buf;
  1254. X    ifc.ifc_len = sizeof (buf);
  1255. X
  1256. X    if (ioctl(s, SIOCGIFCONF, &ifc) < 0) {
  1257. X        (void) close(s);
  1258. X        return (-1);
  1259. X    }
  1260. X
  1261. X    /*
  1262. X     * if_count here is the count of possible
  1263. X     * interfaces we may be interested in... actual
  1264. X     * interfaces may be less (some may not be internet,
  1265. X     * not all are necessarily up, etc.)
  1266. X     */
  1267. X
  1268. X    if_count = ifc.ifc_len / sizeof (struct ifreq);
  1269. X
  1270. X    in_ifsni = (struct in_if *) malloc(if_count * sizeof (struct in_if));
  1271. X    if (in_ifsni == 0) {
  1272. X        (void) close(s);
  1273. X        return (-1);
  1274. X    }
  1275. X
  1276. X    for (i = j = 0; i < if_count; ++i) {
  1277. X        ifr = &ifc.ifc_req[i];
  1278. X        if (ioctl(s, SIOCGIFFLAGS, ifr) < 0)
  1279. X            continue;
  1280. X        if ((ifr->ifr_flags & IFF_UP) == 0)
  1281. X            continue;
  1282. X        if (ioctl(s, SIOCGIFADDR, ifr) < 0)
  1283. X            continue;
  1284. X        if (ifr->ifr_addr.sa_family != AF_INET)
  1285. X            continue;
  1286. X        addr = (*(struct sockaddr_in *)&ifr->ifr_addr).sin_addr.s_addr;
  1287. X        in_ifsni[j].i_net = inet_netof(addr);
  1288. X        if (ioctl(s, SIOCGIFNETMASK, ifr) < 0)
  1289. X            continue;
  1290. X        in_ifsni[j].i_subnetmask =
  1291. X         ntohl((*(struct sockaddr_in *)&ifr->ifr_addr).sin_addr.s_addr);
  1292. X        /*
  1293. X         * The following should "never happen".  But under SunOs
  1294. X         * 3.4, along with the rest of their broken networking code,
  1295. X         * SIOCGIFNETMASK can get a netmask which is 0.  There
  1296. X         * really isn't anything that "right" that we can do
  1297. X         * about it, so we'll set their subnet mask to be their
  1298. X         * *net*work mask.  Which may or may not be right.
  1299. X         */
  1300. X        if (in_ifsni[j].i_subnetmask == 0) {
  1301. X            addr = ntohl(addr);
  1302. X            if (IN_CLASSA(addr))
  1303. X                in_ifsni[j].i_subnetmask = IN_CLASSA_NET;
  1304. X            else if (IN_CLASSB(addr))
  1305. X                in_ifsni[j].i_subnetmask = IN_CLASSB_NET;
  1306. X            else if (IN_CLASSC(addr))
  1307. X                in_ifsni[j].i_subnetmask = IN_CLASSC_NET;
  1308. X            else            /* what to do ... */
  1309. X                in_ifsni[j].i_subnetmask = IN_CLASSC_NET;
  1310. X        } else
  1311. X            in_ifsni[j].i_bitshift = bsr(in_ifsni[j].i_subnetmask);
  1312. X        j++;
  1313. X    }
  1314. X
  1315. X    if_count = j;
  1316. X
  1317. X    (void) close(s);
  1318. X
  1319. X    return (if_count);
  1320. X
  1321. X#else    /* hard-coded subnets */
  1322. X
  1323. X    if_count = 1;
  1324. X
  1325. X    in_ifsni = (struct in_if *) malloc(if_count * sizeof (struct in_if));
  1326. X    if (in_ifsni == 0) {
  1327. X        return (-1);
  1328. X    }
  1329. X    in_ifsni[0].i_net = 0;
  1330. X    in_ifsni[0].i_subnetmask = NETMASK;
  1331. X    in_ifsni[0].i_bitshift = bsr(in_ifsni[0].i_subnetmask);
  1332. X    return (if_count);
  1333. X#endif
  1334. X}
  1335. X
  1336. X
  1337. X/*
  1338. X * Return the (sub)network number from an internet address.
  1339. X * "in" is in NBO, return value in host byte order.
  1340. X * If "in" is not a subnet, return 0.
  1341. X */
  1342. X
  1343. u_long
  1344. inet_snetof(in)
  1345. X    u_long    in;
  1346. X{
  1347. X    register int    j;
  1348. X    register u_long    i = ntohl(in);
  1349. X    register u_long    net;
  1350. X    u_long        inet_netof(), inet_lnaof();
  1351. X
  1352. X    net = inet_netof(in);
  1353. X
  1354. X    /*
  1355. X     * Check whether network is a subnet;
  1356. X     * if so, return subnet number.
  1357. X     */
  1358. X    for (j = 0; j < if_count; ++j)
  1359. X#ifdef NETMASK
  1360. X        if (1) {
  1361. X#else
  1362. X        if (net == in_ifsni[j].i_net) {
  1363. X#endif
  1364. X            net = i & in_ifsni[j].i_subnetmask;
  1365. X            if (inet_lnaof(htonl(net)) == 0)
  1366. X                return (0);
  1367. X            else
  1368. X                return (net >> in_ifsni[j].i_bitshift);
  1369. X        }
  1370. X
  1371. X    return (0);
  1372. X}
  1373. X
  1374. X
  1375. X/*
  1376. X * Return the number of bits required to
  1377. X * shift right a mask into a getnetent-able entitity.
  1378. X */
  1379. X
  1380. bsr(mask)
  1381. X    register int    mask;
  1382. X{
  1383. X    register int    count = 0;
  1384. X
  1385. X    if (mask == 0)        /* "never happen", except with SunOs 3.4 */
  1386. X        return (0);
  1387. X
  1388. X    while ((mask & 1) == 0) {
  1389. X        ++count;
  1390. X        mask >>= 1;
  1391. X    }
  1392. X#ifdef DAMAGED_NETMASK
  1393. X    count /= 8;            /* XXX gag retch puke barf */
  1394. X    count *= 8;
  1395. X#endif
  1396. X    return (count);
  1397. X}
  1398. X
  1399. X#endif
  1400. END_OF_FILE
  1401. if test 6358 -ne `wc -c <'./server/subnet.c'`; then
  1402.     echo shar: \"'./server/subnet.c'\" unpacked with wrong size!
  1403. fi
  1404. # end of './server/subnet.c'
  1405. fi
  1406. if test -f './xmit/get_tcp_conn.c' -a "${1}" != "-c" ; then 
  1407.   echo shar: Will not clobber existing file \"'./xmit/get_tcp_conn.c'\"
  1408. else
  1409. echo shar: Extracting \"'./xmit/get_tcp_conn.c'\" \(7210 characters\)
  1410. sed "s/^X//" >'./xmit/get_tcp_conn.c' <<'END_OF_FILE'
  1411. X/*
  1412. X** Routines to open a TCP connection
  1413. X**
  1414. X** New version that supports the old (pre 4.2 BSD) socket calls,
  1415. X** and systems with the old (pre 4.2 BSD) hostname lookup stuff.
  1416. X** Compile-time options are:
  1417. X**
  1418. X**    USG        - you're on System III/V (you have my sympathies)
  1419. X**    NONETDB        - old hostname lookup with rhost()
  1420. X**    OLDSOCKET    - different args for socket() and connect()
  1421. X**
  1422. X** Erik E. Fair <fair@ucbarpa.berkeley.edu>
  1423. X**
  1424. X*/
  1425. X
  1426. X#include <sys/types.h>
  1427. X#include <sys/socket.h>
  1428. X#include <netinet/in.h>
  1429. X#include <ctype.h>
  1430. X#include <stdio.h>
  1431. X#include "get_tcp_conn.h"
  1432. X#ifndef    NONETDB
  1433. X#include <netdb.h>
  1434. X#endif    NONETDB
  1435. X
  1436. extern    int    errno;
  1437. extern    char    *Pname;
  1438. extern    char    *errmsg();
  1439. X#ifndef    htons
  1440. extern    u_short    htons();
  1441. X#endif    htons
  1442. X#ifndef    NONETDB
  1443. extern    char    *inet_ntoa();
  1444. extern    u_long    inet_addr();
  1445. X#else
  1446. X/*
  1447. X * inet_addr for EXCELAN (which does not have it!)
  1448. X *
  1449. X */
  1450. u_long
  1451. inet_addr(cp)
  1452. register char    *cp;
  1453. X{
  1454. X    u_long val, base, n;
  1455. X    register char c;
  1456. X     u_long octet[4], *octetptr = octet;
  1457. X#ifndef    htonl
  1458. X    extern    u_long    htonl();
  1459. X#endif    htonl
  1460. again:
  1461. X    /*
  1462. X     * Collect number up to ``.''.
  1463. X     * Values are specified as for C:
  1464. X     * 0x=hex, 0=octal, other=decimal.
  1465. X     */
  1466. X    val = 0; base = 10;
  1467. X    if (*cp == '0')
  1468. X        base = 8, cp++;
  1469. X    if (*cp == 'x' || *cp == 'X')
  1470. X        base = 16, cp++;
  1471. X    while (c = *cp) {
  1472. X        if (isdigit(c)) {
  1473. X            val = (val * base) + (c - '0');
  1474. X            cp++;
  1475. X            continue;
  1476. X        }
  1477. X        if (base == 16 && isxdigit(c)) {
  1478. X            val = (val << 4) + (c + 10 - (islower(c) ? 'a' : 'A'));
  1479. X            cp++;
  1480. X            continue;
  1481. X        }
  1482. X        break;
  1483. X    }
  1484. X    if (*cp == '.') {
  1485. X        /*
  1486. X         * Internet format:
  1487. X         *    a.b.c.d
  1488. X         *    a.b.c    (with c treated as 16-bits)
  1489. X         *    a.b    (with b treated as 24 bits)
  1490. X         */
  1491. X        if (octetptr >= octet + 4)
  1492. X            return (-1);
  1493. X        *octetptr++ = val, cp++;
  1494. X        goto again;
  1495. X    }
  1496. X    /*
  1497. X     * Check for trailing characters.
  1498. X     */
  1499. X    if (*cp && !isspace(*cp))
  1500. X        return (-1);
  1501. X    *octetptr++ = val;
  1502. X    /*
  1503. X     * Concoct the address according to
  1504. X     * the number of octet specified.
  1505. X     */
  1506. X    n = octetptr - octet;
  1507. X    switch (n) {
  1508. X
  1509. X    case 1:                /* a -- 32 bits */
  1510. X        val = octet[0];
  1511. X        break;
  1512. X
  1513. X    case 2:                /* a.b -- 8.24 bits */
  1514. X        val = (octet[0] << 24) | (octet[1] & 0xffffff);
  1515. X        break;
  1516. X
  1517. X    case 3:                /* a.b.c -- 8.8.16 bits */
  1518. X        val = (octet[0] << 24) | ((octet[1] & 0xff) << 16) |
  1519. X            (octet[2] & 0xffff);
  1520. X        break;
  1521. X
  1522. X    case 4:                /* a.b.c.d -- 8.8.8.8 bits */
  1523. X        val = (octet[0] << 24) | ((octet[1] & 0xff) << 16) |
  1524. X              ((octet[2] & 0xff) << 8) | (octet[3] & 0xff);
  1525. X        break;
  1526. X
  1527. X    default:
  1528. X        return (-1);
  1529. X    }
  1530. X    val = htonl(val);
  1531. X    return (val);
  1532. X}
  1533. X
  1534. char *
  1535. inet_ntoa(in)
  1536. struct in_addr in;
  1537. X{
  1538. X    static char address[20];
  1539. X
  1540. X    sprintf(address, "%u.%u.%u.%u",
  1541. X             (in.s_addr>>24)&0xff,
  1542. X             (in.s_addr>>16)&0xff,
  1543. X             (in.s_addr>>8 )&0xff,
  1544. X             (in.s_addr    )&0xff);
  1545. X    return(address);
  1546. X}
  1547. X#endif    NONETDB
  1548. X
  1549. X#ifdef    USG
  1550. void
  1551. bcopy(s, d, l)
  1552. register caddr_t s, d;
  1553. register int l;
  1554. X{
  1555. X    while (l-- > 0)    *d++ = *s++;
  1556. X}
  1557. X#endif    USG
  1558. X
  1559. X/*
  1560. X** Take the name of an internet host in ASCII (this may either be its
  1561. X** official host name or internet number (with or without enclosing
  1562. X** backets [])), and return a list of internet addresses.
  1563. X**
  1564. X** returns NULL for failure to find the host name in the local database,
  1565. X** or for a bad internet address spec.
  1566. X*/
  1567. u_long **
  1568. name_to_address(host)
  1569. char    *host;
  1570. X{
  1571. X    static    u_long    *host_addresses[2];
  1572. X    static    u_long    haddr;
  1573. X
  1574. X    if (host == (char *)NULL) {
  1575. X        return((u_long **)NULL);
  1576. X    }
  1577. X
  1578. X    host_addresses[0] = &haddr;
  1579. X    host_addresses[1] = (u_long *)NULL;
  1580. X
  1581. X    /*
  1582. X    ** Is this an ASCII internet address? (either of [10.0.0.78] or
  1583. X    ** 10.0.0.78). We get away with the second test because hostnames
  1584. X    ** and domain labels are not allowed to begin in numbers.
  1585. X    ** (cf. RFC952, RFC882).
  1586. X    */
  1587. X    if (*host == '[' || isdigit(*host)) {
  1588. X        char    namebuf[128];
  1589. X        register char    *cp = namebuf;
  1590. X
  1591. X        /*
  1592. X        ** strip brackets [] or anything else we don't want.
  1593. X        */
  1594. X        while(*host != '\0' && cp < &namebuf[sizeof(namebuf)]) {
  1595. X            if (isdigit(*host) || *host == '.')
  1596. X                *cp++ = *host++;    /* copy */
  1597. X            else
  1598. X                host++;            /* skip */
  1599. X        }
  1600. X        *cp = '\0';
  1601. X        haddr = inet_addr(namebuf);
  1602. X        return(&host_addresses[0]);
  1603. X    } else {
  1604. X#ifdef    NONETDB
  1605. X        extern    u_long    rhost();
  1606. X
  1607. X        /* lint is gonna bitch about this (comparing an unsigned?!) */
  1608. X        if ((haddr = rhost(&host)) == FAIL)
  1609. X            return((u_long **)NULL);    /* no such host */
  1610. X        return(&host_addresses[0]);
  1611. X#else
  1612. X        struct hostent    *hstp = gethostbyname(host);
  1613. X
  1614. X        if (hstp == NULL) {
  1615. X            return((u_long **)NULL);    /* no such host */
  1616. X        }
  1617. X
  1618. X        if (hstp->h_length != sizeof(u_long))
  1619. X            abort();    /* this is fundamental */
  1620. X#ifndef    h_addr
  1621. X        /* alignment problems (isn't dbm wonderful?) */
  1622. X        bcopy((caddr_t)hstp->h_addr, (caddr_t)&haddr, sizeof(haddr));
  1623. X        return(&host_addresses[0]);
  1624. X#else
  1625. X        return((u_long **)hstp->h_addr_list);
  1626. X#endif    h_addr
  1627. X#endif    NONETDB
  1628. X    }
  1629. X}
  1630. X
  1631. X/*
  1632. X** Get a service port number from a service name (or ASCII number)
  1633. X**
  1634. X** Return zero if something is wrong (that's a reserved port)
  1635. X*/
  1636. X#ifdef    NONETDB
  1637. static struct Services {
  1638. X    char    *name;
  1639. X    u_short    port;
  1640. X} Services[] = {
  1641. X    {"nntp",    IPPORT_NNTP},        /* RFC977 */
  1642. X    {"smtp",    IPPORT_SMTP},        /* RFC821 */
  1643. X    {"name",    IPPORT_NAMESERVER},    /* RFC881, RFC882, RFC883 */
  1644. X    {"time",    IPPORT_TIMESERVER},    /* RFC868 */
  1645. X    {"echo",    IPPORT_ECHO},        /* RFC862 */
  1646. X    {"discard",    IPPORT_DISCARD},    /* RFC863 */
  1647. X    {"daytime",    IPPORT_DAYTIME},    /* RFC867 */
  1648. X    {"login",    IPPORT_LOGINSERVER},    /* N/A - 4BSD specific */
  1649. X};
  1650. X#endif    NONETDB
  1651. X
  1652. u_short
  1653. gservice(serv, proto)
  1654. char    *serv, *proto;
  1655. X{
  1656. X    if (serv == (char *)NULL || proto == (char *)NULL)
  1657. X        return((u_short)0);
  1658. X
  1659. X    if (isdigit(*serv)) {
  1660. X        return(htons((u_short)(atoi(serv))));
  1661. X    } else {
  1662. X#ifdef    NONETDB
  1663. X        register int    i;
  1664. X
  1665. X        for(i = 0; i < (sizeof(Services) / sizeof(struct Services)); i++) {
  1666. X            if (strcmp(serv, Services[i].name) == 0)
  1667. X                return(htons(Services[i].port));
  1668. X        }
  1669. X        return((u_short)0);
  1670. X#else
  1671. X        struct servent    *srvp = getservbyname(serv, proto);
  1672. X
  1673. X        if (srvp == (struct servent *)NULL)
  1674. X            return((u_short)0);
  1675. X        return((u_short)srvp->s_port);
  1676. X#endif    NONETDB
  1677. X    }
  1678. X}
  1679. X
  1680. X/*
  1681. X** given a host name (either name or internet address) and service name
  1682. X** (or port number) (both in ASCII), give us a TCP connection to the
  1683. X** requested service at the requested host (or give us FAIL).
  1684. X*/
  1685. get_tcp_conn(host, serv)
  1686. char    *host, *serv;
  1687. X{
  1688. X    register int    sock;
  1689. X    u_long    **addrlist;
  1690. X    struct sockaddr_in    sadr;
  1691. X#ifdef    OLDSOCKET
  1692. X    struct sockproto    sp;
  1693. X
  1694. X    sp.sp_family    = (u_short)AF_INET;
  1695. X    sp.sp_protocol    = (u_short)IPPROTO_TCP;
  1696. X#endif    OLDSOCKET
  1697. X
  1698. X    if ((addrlist = name_to_address(host)) == (u_long **)NULL) {
  1699. X        return(NOHOST);
  1700. X    }
  1701. X
  1702. X    sadr.sin_family = (u_short)AF_INET;    /* Only internet for now */
  1703. X    if ((sadr.sin_port = gservice(serv, "tcp")) == 0)
  1704. X        return(NOSERVICE);
  1705. X
  1706. X    for(; *addrlist != (u_long *)NULL; addrlist++) {
  1707. X        bcopy((caddr_t)*addrlist, (caddr_t)&sadr.sin_addr,
  1708. X            sizeof(sadr.sin_addr));
  1709. X
  1710. X#ifdef    OLDSOCKET
  1711. X        if ((sock = socket(SOCK_STREAM, &sp, (struct sockaddr *)NULL, 0)) < 0)
  1712. X            return(FAIL);
  1713. X
  1714. X        if (connect(sock, (struct sockaddr *)&sadr) < 0) {
  1715. X#else
  1716. X        if ((sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0)
  1717. X            return(FAIL);
  1718. X
  1719. X        if (connect(sock, (struct sockaddr *)&sadr, sizeof(sadr)) < 0) {
  1720. X#endif    OLDSOCKET
  1721. X            int    e_save = errno;
  1722. X
  1723. X            fprintf(stderr, "%s: %s [%s]: %s\n", Pname, host,
  1724. X                inet_ntoa(sadr.sin_addr), errmsg(errno));
  1725. X            (void) close(sock);    /* dump descriptor */
  1726. X            errno = e_save;
  1727. X        } else
  1728. X            return(sock);
  1729. X    }
  1730. X    return(FAIL);
  1731. X}
  1732. END_OF_FILE
  1733. if test 7210 -ne `wc -c <'./xmit/get_tcp_conn.c'`; then
  1734.     echo shar: \"'./xmit/get_tcp_conn.c'\" unpacked with wrong size!
  1735. fi
  1736. # end of './xmit/get_tcp_conn.c'
  1737. fi
  1738. if test -f './xmit/shlock.c' -a "${1}" != "-c" ; then 
  1739.   echo shar: Will not clobber existing file \"'./xmit/shlock.c'\"
  1740. else
  1741. echo shar: Extracting \"'./xmit/shlock.c'\" \(6278 characters\)
  1742. sed "s/^X//" >'./xmit/shlock.c' <<'END_OF_FILE'
  1743. X/*
  1744. X** Program to produce reliable locks for shell scripts.
  1745. X** Algorithmn suggested by Peter Honeyman, January 1984,
  1746. X** in connection with HoneyDanBer UUCP.
  1747. X**
  1748. X** I tried extending this to handle shared locks in November 1987,
  1749. X** and ran into to some fundamental problems:
  1750. X**
  1751. X**    Neither 4.3 BSD nor System V have an open(2) with locking,
  1752. X**    so that you can open a file and have it locked as soon as
  1753. X**    it's real; you have to make two system calls, and there's
  1754. X**    a race...
  1755. X**
  1756. X**    When removing dead process id's from a list in a file,
  1757. X**    you need to truncate the file (you don't want to create a
  1758. X**    new one; see above); unfortunately for the portability of
  1759. X**    this program, only 4.3 BSD has ftruncate(2).
  1760. X**
  1761. X** Erik E. Fair <fair@ucbarpa.berkeley.edu>, November 8, 1987
  1762. X*/
  1763. X
  1764. X#include <stdio.h>
  1765. X#include <sys/types.h>
  1766. X#include <fcntl.h>            /* Needed on hpux */
  1767. X#include <sys/file.h>
  1768. X#include <errno.h>
  1769. X
  1770. X#define    LOCK_SET    0
  1771. X#define    LOCK_FAIL    1
  1772. X
  1773. X#define    FAIL        (-1)
  1774. X
  1775. X#define    TRUE    1
  1776. X#define    FALSE    0
  1777. X
  1778. X#ifdef USG
  1779. X#define    index    strchr
  1780. X#define    rindex    strrchr
  1781. X#endif
  1782. X
  1783. int    Debug = FALSE;
  1784. char    *Pname;
  1785. char    *USAGE = "%s: USAGE: shlock -f file -p pid [-d]\n";
  1786. char    *errmsg();
  1787. char    *xtmpfile();
  1788. X
  1789. X#define    dprintf    if (Debug) printf
  1790. X
  1791. extern    int    errno;
  1792. extern    char    *rindex();
  1793. extern    char    *strcpy();
  1794. extern    char    *strcat();
  1795. X
  1796. main(ac, av)
  1797. int    ac;
  1798. char    *av[];
  1799. X{
  1800. X    register int    x;
  1801. X    char    *file;
  1802. X    int    pid;
  1803. X
  1804. X    Pname = ((Pname = rindex(av[0], '/')) ? Pname + 1 : av[0]);
  1805. X
  1806. X    for(x = 1; x < ac; x++) {
  1807. X        if (av[x][0] == '-') {
  1808. X            switch(av[x][1]) {
  1809. X            case 'd':
  1810. X                Debug = TRUE;
  1811. X                break;
  1812. X            case 'p':
  1813. X                if (strlen(av[x]) > 2) {
  1814. X                    pid = atoi(&av[x][2]);
  1815. X                } else {
  1816. X                    pid = atoi(av[++x]);
  1817. X                }
  1818. X                break;
  1819. X            case 'f':
  1820. X                if (strlen(av[x]) > 2) {
  1821. X                    file = &av[x][2];
  1822. X                } else {
  1823. X                    file = av[++x];
  1824. X                }
  1825. X                break;
  1826. X            default:
  1827. X                fprintf(stderr, USAGE, Pname);
  1828. X                exit(LOCK_FAIL);
  1829. X            }
  1830. X        }
  1831. X    }
  1832. X    if (pid == 0 || file == (char *)NULL) {
  1833. X        fprintf(stderr, USAGE, Pname);
  1834. X        exit(LOCK_FAIL);
  1835. X    }
  1836. X
  1837. X    exit(mklock(file, pid) ? LOCK_SET : LOCK_FAIL);
  1838. X}
  1839. X
  1840. char *
  1841. errmsg(n)
  1842. register int    n;
  1843. X{
  1844. X    extern    int    sys_nerr;
  1845. X    extern     char    *sys_errlist[];
  1846. X
  1847. X    return((n >= 0 && n < sys_nerr) ? sys_errlist[n] : "unknown error");
  1848. X}
  1849. X
  1850. mklock(file, pid)
  1851. char    *file;
  1852. int    pid;
  1853. X{
  1854. X    register char    *tmp;
  1855. X    register int    retcode = FALSE;
  1856. X    char    *e_unlk = "%s: unlink(%s): %s\n";
  1857. X
  1858. X    dprintf("%s: trying lock <%s> for process %d\n", Pname, file, pid);
  1859. X    if ((tmp = xtmpfile(file, pid)) == (char *)NULL)
  1860. X        return(FALSE);
  1861. X
  1862. linkloop:
  1863. X    if (link(tmp, file) < 0) {
  1864. X        switch(errno) {
  1865. X        case EEXIST:
  1866. X            dprintf("%s: lock <%s> already exists\n", Pname, file);
  1867. X            if (cklock(file)) {
  1868. X                dprintf("%s: extant lock is valid\n", Pname);
  1869. X                break;
  1870. X            } else {
  1871. X                dprintf("%s: lock is invalid, removing\n",
  1872. X                    Pname);
  1873. X                if (unlink(file) < 0) {
  1874. X                    fprintf(stderr, e_unlk,
  1875. X                        Pname, file, errmsg(errno));
  1876. X                    break;
  1877. X                }
  1878. X            }
  1879. X            /*
  1880. X            ** I hereby profane the god of structured programming,
  1881. X            ** Edsgar Dijkstra
  1882. X            */
  1883. X            goto linkloop;
  1884. X        default:
  1885. X            fprintf(stderr, "%s: link(%s, %s): %s\n",
  1886. X                Pname, tmp, file, errmsg(errno));
  1887. X            break;
  1888. X        }
  1889. X    } else {
  1890. X        dprintf("%s: got lock <%s>\n", Pname, file);
  1891. X        retcode = TRUE;
  1892. X    }
  1893. X    if (unlink(tmp) < 0) {
  1894. X        fprintf(stderr, e_unlk, Pname, tmp, errmsg(errno));
  1895. X    }
  1896. X    return(retcode);
  1897. X}
  1898. X
  1899. X/*
  1900. X** Does the PID exist?
  1901. X** Send null signal to find out.
  1902. X*/
  1903. p_exists(pid)
  1904. int    pid;
  1905. X{
  1906. X    dprintf("%s: process %d is ", Pname, pid);
  1907. X    if (pid <= 0) {
  1908. X        dprintf("invalid\n");
  1909. X        return(FALSE);
  1910. X    }
  1911. X    if (kill(pid, 0) < 0) {
  1912. X        switch(errno) {
  1913. X        case ESRCH:
  1914. X            dprintf("dead\n");
  1915. X            return(FALSE);    /* pid does not exist */
  1916. X        case EPERM:
  1917. X            dprintf("alive\n");
  1918. X            return(TRUE);    /* pid exists */
  1919. X        default:
  1920. X            dprintf("state unknown: %s\n", errmsg(errno));
  1921. X            return(TRUE);    /* be conservative */
  1922. X        }
  1923. X    }
  1924. X    dprintf("alive\n");
  1925. X    return(TRUE);    /* pid exists */
  1926. X}
  1927. X
  1928. X/*
  1929. X** Check the validity of an existing lock file.
  1930. X**
  1931. X**    Read the PID out of the lock
  1932. X**    Send a null signal to determine whether that PID still exists
  1933. X**    Existence (or not) determines the validity of the lock.
  1934. X**
  1935. X**    Two bigs wins to this algorithmn:
  1936. X**
  1937. X**    o    Locks do not survive crashes of either the system or the
  1938. X**            application by any appreciable period of time.
  1939. X**
  1940. X**    o    No clean up to do if the system or application crashes.
  1941. X**
  1942. X*/
  1943. X
  1944. cklock(file)
  1945. char    *file;
  1946. X{
  1947. X    register int    fd = open(file, O_RDONLY);
  1948. X    register int    len;
  1949. X    char    buf[BUFSIZ];
  1950. X
  1951. X    dprintf("%s: checking extant lock <%s>\n", Pname, file);
  1952. X    if (fd < 0) {
  1953. X        fprintf(stderr,"%s: open(%s): %s\n", Pname, file, errmsg(errno));
  1954. X        return(TRUE);    /* might or might not; conservatism */
  1955. X    }
  1956. X
  1957. X    if ((len = read(fd, buf, sizeof(buf))) <= 0) {
  1958. X        close(fd);
  1959. X        dprintf("%s: lock file format error\n", Pname);
  1960. X        return(FALSE);
  1961. X    }
  1962. X    close(fd);
  1963. X    buf[len + 1] = '\0';
  1964. X    return(p_exists(atoi(buf)));
  1965. X}
  1966. X
  1967. X/*
  1968. X** Create a temporary file, all ready to lock with.
  1969. X** The file arg is so we get the filename right, if he
  1970. X** gave us a full path, instead of using the current directory
  1971. X** which might not be in the same filesystem.
  1972. X*/
  1973. char *
  1974. xtmpfile(file, pid)
  1975. char    *file;
  1976. int    pid;
  1977. X{
  1978. X    register int    fd;
  1979. X    register int    len;
  1980. X    char    *cp, buf[BUFSIZ];
  1981. X    static char    tempname[BUFSIZ];
  1982. X
  1983. X    sprintf(buf, "shlock%d", getpid());
  1984. X    if ((cp = rindex(strcpy(tempname, file), '/')) != (char *)NULL) {
  1985. X        *++cp = '\0';
  1986. X        (void) strcat(tempname, buf);
  1987. X    } else
  1988. X        (void) strcpy(tempname, buf);
  1989. X    dprintf("%s: temporary filename: %s\n", Pname, tempname);
  1990. X
  1991. X    sprintf(buf, "%d\n", pid);
  1992. X    len = strlen(buf);
  1993. openloop:
  1994. X    if ((fd = open(tempname, O_RDWR|O_CREAT|O_EXCL, 0644)) < 0) {
  1995. X        switch(errno) {
  1996. X        case EEXIST:
  1997. X            dprintf("%s: file %s exists already.\n",
  1998. X                Pname, tempname);
  1999. X            if (unlink(tempname) < 0) {
  2000. X                fprintf(stderr, "%s: unlink(%s): %s\n",
  2001. X                    Pname, tempname, errmsg(errno));
  2002. X                return((char *)NULL);
  2003. X            }
  2004. X            /*
  2005. X            ** Further profanity
  2006. X            */
  2007. X            goto openloop;
  2008. X        default:
  2009. X            fprintf(stderr, "%s: open(%s): %s\n",
  2010. X                Pname, tempname, errmsg(errno));
  2011. X            return((char *)NULL);
  2012. X        }
  2013. X    }
  2014. X
  2015. X    /*
  2016. X    ** Write the PID into the temporary file before attempting to link
  2017. X    ** to the actual lock file. That way we have a valid lock the instant
  2018. X    ** the link succeeds.
  2019. X    */
  2020. X    if (write(fd, buf, len) < 0) {
  2021. X        fprintf(stderr, "%s: write(%s,%d): %s\n",
  2022. X            Pname, tempname, pid, errmsg(errno));
  2023. X        (void) close(fd);
  2024. X        return((char *)NULL);
  2025. X    }
  2026. X    (void) close(fd);
  2027. X    return(tempname);
  2028. X}
  2029. END_OF_FILE
  2030. if test 6278 -ne `wc -c <'./xmit/shlock.c'`; then
  2031.     echo shar: \"'./xmit/shlock.c'\" unpacked with wrong size!
  2032. fi
  2033. # end of './xmit/shlock.c'
  2034. fi
  2035. echo shar: End of archive 5 \(of 9\).
  2036. cp /dev/null ark5isdone
  2037. MISSING=""
  2038. for I in 1 2 3 4 5 6 7 8 9 ; do
  2039.     if test ! -f ark${I}isdone ; then
  2040.     MISSING="${MISSING} ${I}"
  2041.     fi
  2042. done
  2043. if test "${MISSING}" = "" ; then
  2044.     echo You have unpacked all 9 archives.
  2045.     rm -f ark[1-9]isdone ark[1-9][0-9]isdone
  2046. else
  2047.     echo You still need to unpack the following archives:
  2048.     echo "        " ${MISSING}
  2049. fi
  2050. ##  End of shell archive.
  2051. exit 0
  2052.